package priority;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PriorityScheduling {
    private PCB head;
    private static List<PCB> pcbList;

    //随机获取优先级和需要运行时间
    public static int generateRandomNeedTime() {
        return new Random().nextInt(6);
    }

    public static int generateRandomPriority() {
        return new Random().nextInt(6);
    }

    //按优先级降序将PCB对象进行插入
    public void addPCB(PCB node) {
        if (node.getNeedTime() == 0) {//如果进程所需运行时间为0,设置其状态改为E，退出队列
            node.setState("E");
            System.out.println(node.getName() + "退出进程队列");
            return;
        }
        /*插在头结点处
         * 1.此时第一个进程进入队列，没有节点，
         * 2.插入进程优先级大于当前头节点进程
         * */
        if ((this.head == null) || (node.getPriority() > this.head.getPriority())) {
            node.setNext(this.head);
            this.head = node;
            return;
        }
        PCB cur = this.head.getNext();
        PCB parent = this.head;
        while (cur != null) {
            if (node.getPriority() > cur.getPriority()) {
                node.setNext(parent.getNext());
                parent.setNext(node);
                return;
            }
            parent = cur;
            cur = cur.getNext();
        }
        //优先级最低
        //与当前的最后一个节点的优先级相同
        parent.setNext(node);
        node.setNext(null);
    }

    //按优先级运行的函数实现
    public void runPCB() {
        int cpuTime = 1;
        while (this.head != null) {
            //运行头结点进程，优先级最高
            PCB pcb = this.head;
            this.head = this.head.getNext();//指向下一个进程
            System.out.println("CPUTIME:" + cpuTime + "    " + "需要调度执行的进程："+pcb.getName());
            pcb.setPriority(pcb.getPriority() - 1);//pcb的运行优先级-1
            pcb.setNeedTime(pcb.getNeedTime() - 1); //pcb的运行时间-1
            pcb.setRoundTime(cpuTime);//周转时间为当前CPU已经运转的时间
            pcb.setWaitingTime(pcb.getWaitingTime() + cpuTime - pcb.getLastTime() - 1);
            pcb.setLastTime(cpuTime);
            pcb.setCpuTime(pcb.getCpuTime()+1);

            pcb.setState("W");//改变pcb状态为working
            addPCB(pcb);//执行后重新加入队列
            display();//打印输出结果列表
            if (pcb.getState().equals("W"))
                pcb.setState("R");//如果没有结束将状态重新设为就绪
            cpuTime++;
        }
        System.out.println("所有进程执行完毕");
        System.out.println("NAME   RoundTime   WaitingTime");//输出运行结果
        for (PCB pcb : pcbList) {
            System.out.println(pcb.getName() + "      " + pcb.getRoundTime() + "             " + pcb.getWaitingTime());
        }
    }

    //展示本次执行结果函数
    public void display() {

        System.out.println("NAME  CPUTIME  NEEDTIME  PRIORITY  STATE");
        for (PCB pcb : pcbList) {
            if (pcb.getState().equals("R")) {
                if (pcb.getCpuTime() != 0) pcb.setCpuTime(pcb.getCpuTime() + 1);
                System.out.println(pcb.getName() + "       " + pcb.getCpuTime() + "        " +
                        pcb.getNeedTime() + "         " + pcb.getPriority() +
                        "    " + "ready");
            } else if (pcb.getState().equals("E"))
                System.out.println(pcb.getName() + "       " + pcb.getCpuTime() + "        " +
                        pcb.getNeedTime() + "         " + pcb.getPriority() +
                        "    " + "finish");
            else
                System.out.println(pcb.getName() + "       " + pcb.getCpuTime() + "        " +
                        pcb.getNeedTime() + "         " + pcb.getPriority() +
                        "    " + "working");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        pcbList = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            pcbList.add(new PCB("P" + i, generateRandomPriority(),
                    generateRandomNeedTime()));
        }
        PriorityScheduling processScheduling = new PriorityScheduling();
        System.out.println("INPUT NAME  NEEDTIME  PRIORITY ");
        for (PCB pcb : pcbList) {//初始化输出
            System.out.println("     " + pcb.getName() + "          " +
                    pcb.getNeedTime() + "        " + pcb.getPriority() + "      ");
        }
        System.out.println("CPUTIME:0 ");
        processScheduling.display();//初始状态展示
        for (PCB p : pcbList) {//将列表中依次加入队列
            processScheduling.addPCB(p);
        }
        processScheduling.runPCB();//运行
    }
}